package cn.json.enums;


import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.json.annotation.Statement;
import cn.json.provider.StatementTypeProvider;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * &#064;Time 2024 七月 星期二 13:28
 *
 * @author ShangGuan
 */
public enum StatementType implements StatementTypeProvider {


    /**
     * 对象
     */
    OBJECT {
        /**
         * 获取对象的值 {@see StatementType.OBJECT}
         *
         * @param annotation 注释
         * @param jsonObject json对象
         * @return {@link Object}
         */

        @SneakyThrows
        @Override
        public Object getValue(Statement annotation, JSONObject jsonObject) {
            if (!annotation.type().equals(StatementType.OBJECT)) {
                throw new RuntimeException("StatementType type is OBJECT");
            }
            String value = annotation.value();
            String className = annotation.source();
            JSONObject itemJsonObject = JSONUtil.parseObj(jsonObject.get(value));
            Class<?> aClass = Class.forName(className);
            Object entity = aClass.newInstance();
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Statement annotationItem = field.getAnnotation(Statement.class);
                if (annotationItem != null) {
                    Object filedTargetValue = annotationItem.type().getValue(annotationItem, itemJsonObject);
                    field.set(entity, filedTargetValue);
                    continue;
                }
                field.set(entity, itemJsonObject.get(field.getName(), String.class));
            }
            return entity;
        }
    },
    /**
     * 对象列表
     */
    OBJECT_LIST {
        /**
         * 获取对象的值 {@see StatementType.OBJECT}
         *
         * @param annotation 注释
         * @param jsonObject json对象
         * @return {@link Object}
         */
        @Override
        @SneakyThrows
        public Object getValue(Statement annotation, JSONObject jsonObject) {
            if (!annotation.type().equals(StatementType.OBJECT_LIST)) {
                throw new RuntimeException("StatementType type is OBJECT");
            }
            List<Object> result = new ArrayList<>();
            String value = annotation.value();
            String className = annotation.source();
            JSONArray itemJsonObject = JSONUtil.parseArray(jsonObject.get(value));
            Class<?> aClass = Class.forName(className);
            Field[] fields = aClass.getDeclaredFields();
            for (Object item : itemJsonObject) {
                Object entity = aClass.newInstance();
                JSONObject jsonObjectItem = JSONUtil.parseObj(item);
                for (Field field : fields) {
                    field.setAccessible(true);
                    Statement annotationItem = field.getAnnotation(Statement.class);
                    if (annotationItem != null) {
                        Object filedTargetValue = annotationItem.type().getValue(annotationItem, jsonObjectItem);
                        if (filedTargetValue == null) continue;
                        field.set(entity, filedTargetValue);
                        continue;
                    }
                    field.set(entity, jsonObjectItem.get(field.getName(), String.class));
                }
                result.add(entity);

            }
            return result;
        }
    },

    /**
     * 不做处理
     */
    NO {
        @Override
        public Object getValue(Statement annotation, JSONObject source) {
            return null;
        }
    },

    /**
     * 列表
     */
    List {
        /**
         * 获取对象的值 {@see StatementType.OBJECT}
         *
         * @param annotation 注释
         * @param jsonObject json对象
         * @return {@link Object}
         */
        @Override
        public Object getValue(Statement annotation, JSONObject jsonObject) {
            if (!annotation.type().equals(StatementType.List)) {
                throw new RuntimeException("StatementType type is List");
            }
            String value = annotation.value();
            JSONArray jsonArray = jsonObject.get(value, JSONArray.class);
            StringBuilder stringBuilder = new StringBuilder();
            Iterator<Object> iterator = jsonArray.stream().iterator();
            while (iterator.hasNext()) {
                Object next = iterator.next();
                String item = String.valueOf(next);
                if (iterator.hasNext()) {
                    stringBuilder.append(item).append(",");
                } else {
                    stringBuilder.append(item);
                }
            }
            return stringBuilder.toString();
        }
    },

    /**
     * 字符对象,统一转化为String类型的
     */
    CHAR_OBJECT {
        /**
         * 获取对象的值 {@see StatementType.CHAR_OBJECT}
         * <pre>
         * {@code
         * cn.json.annotation.@Statement(type=StatementType.CHAR_OBJECT,value="Object.field",source="com.xxx.xx.Object" )
         *  private String name;
         * }
         * </pre>
         * value只能包含一个对象，否则反射抓不到具体实体
         * @param annotation 注释
         * @param jsonObject json对象
         * @return {@link Object}
         */

        public Object getValue(Statement annotation, JSONObject jsonObject) {
            if (!annotation.type().equals(StatementType.CHAR_OBJECT)) {
                throw new RuntimeException("StatementType type is CHAR_OBJECT");
            }
            String[] split = annotation.value().split("\\.");
            return recursion(split, jsonObject);
        }

        /**
         * 通过递归的方式获取source的值。
         * 每次递归的同时会更新array，方式会舍弃array[0]
         *
         * @param array  数组
         * @param source 来源
         * @return {@link Object}
         */

        private Object recursion(String[] array, JSONObject source) {
            Iterator<String> iterator = Arrays.stream(array).iterator();
            while (iterator.hasNext()) {
                String next = iterator.next();
                String o = source.get(next, String.class);
                if (iterator.hasNext()) {
                    //如果下一个不为空
                    JSONObject jsonObject = JSONUtil.parseObj(o);
                    //舍弃array[0]
                    java.util.List<String> strings = Arrays.stream(array).collect(Collectors.toList()).subList(1, array.length);
                    String[] stringArray = strings.toArray(new String[]{});
                    return recursion(stringArray, jsonObject);
                }
                return o;
            }
            return null;
        }
    },
    /**
     * 字符，统一转化为String类型的
     */
    CHAR {
        @Override
        public Object getValue(Statement annotation, JSONObject source) {
            String value = annotation.value();
            return source.get(value, String.class);
        }
    },

    /**
     * 整数
     */
    INT {
        @Override
        public Object getValue(Statement annotation, JSONObject source) {
            String value = annotation.value();
            return source.get(value, Integer.class);
        }
    },


    ;
    public abstract Object getValue(Statement annotation, JSONObject source);



}
